﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MetaSharp.Transformation.Patterns
{
    class ProductionPattern : Pattern
    {
        public Pattern Pattern { get; private set; }
        public Delegate Method { get; private set; }

        public ProductionPattern(Pattern pattern, Delegate method)
            : base(PatternKind.Production)
        {
            this.Pattern = pattern;
            this.Method = method;
        }

        public override PatternMatch Compile()
        {
            var p = Pattern.Compile();
            return s => Target(s, p, Method);
        }

        private static async Task<IMatch> Target(IScope scope, PatternMatch pattern, Delegate production)
        {
            var match = await pattern(scope);
            if (!match.Matched)
                return match;

            var parameters = production.Method.GetParameters();
            var args = new object[parameters.Length];
            for (int x = 0; x < parameters.Length; x++)
            {
                var p = parameters[x];
                var val = match.End.Variables[p.Name];
                args[x] = val;
            }

            var retVal = production.DynamicInvoke(args);
            return match
                .SetValue(retVal)
                .SetEnd(match.End.SetVariables(scope.Variables));
        }
    }
}
